/*
 ***** BEGIN LICENSE BLOCK *****
 * Version: CPL 1.0/GPL 2.0/LGPL 2.1
 *
 * The contents of this file are subject to the Common Public
 * License Version 1.0 (the "License"); you may not use this file
 * except in compliance with the License. You may obtain a copy of
 * the License at http://www.eclipse.org/legal/cpl-v10.html
 *
 * Software distributed under the License is distributed on an "AS
 * IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or
 * implied. See the License for the specific language governing
 * rights and limitations under the License.
 *
 * Copyright (C) 2006-2007 Thomas E Enebo <enebo@acm.org>
 * Copyright (C) 2006-2007 Charles Nutter <headius@headius.com>
 * 
 * Alternatively, the contents of this file may be used under the terms of
 * either of the GNU General Public License Version 2 or later (the "GPL"),
 * or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
 * in which case the provisions of the GPL or the LGPL are applicable instead
 * of those above. If you wish to allow use of your version of this file only
 * under the terms of either the GPL or the LGPL, and not to allow others to
 * use your version of this file under the terms of the CPL, indicate your
 * decision by deleting the provisions above and replace them with the notice
 * and other provisions required by the GPL or the LGPL. If you do not delete
 * the provisions above, a recipient may use your version of this file under
 * the terms of any one of the CPL, the GPL or the LGPL.
 ***** END LICENSE BLOCK *****/
package asruby.runtime {

import asruby.runtime.callsite.InlineCachingCallSite;

import flash.utils.Dictionary;

/**
 *
 * @author headius
 */
public class MethodIndex {
    public static var NAMES: Array =  new Array();
    private static var NUMBERS: Dictionary =  new Dictionary();
    private static var CALL_SITES: Dictionary =  new Dictionary();
    private static var FUNCTIONAL_CALL_SITES: Dictionary =  new Dictionary();
    private static var VARIABLE_CALL_SITES: Dictionary =  new Dictionary();
    
    // ensure zero is devoted to no method name
    public static var NO_INDEX: int =  getIndex("");
    
    // predefine a few other methods we invoke directly elsewhere
    public static var OP_PLUS: int =  getIndex("+");
    public static var OP_MINUS: int =  getIndex("-");
    public static var OP_LT: int =  getIndex("<");
    public static var AREF: int =  getIndex("[]");
    public static var ASET: int =  getIndex("[]=");
    public static var EQUALEQUAL: int =  getIndex("==");
    public static var OP_LSHIFT: int =  getIndex("<<");
    public static var EMPTY_P: int =  getIndex("empty?");
    public static var TO_S: int =  getIndex("to_s");
    public static var TO_I: int =  getIndex("to_i");
    public static var TO_STR: int =  getIndex("to_str");
    public static var TO_ARY: int =  getIndex("to_ary");
    public static var TO_INT: int =  getIndex("to_int");
    public static var TO_F: int =  getIndex("to_f");
    public static var TO_A: int =  getIndex("to_a");
    public static var TO_IO: int =  getIndex("to_io");
    public static var HASH: int =  getIndex("hash");
    public static var OP_GT: int =  getIndex(">");
    public static var OP_TIMES: int =  getIndex("*");
    public static var OP_LE: int =  getIndex("<=");
    public static var OP_SPACESHIP: int =  getIndex("<=>");
    public static var OP_EQQ: int =  getIndex("===");
    public static var EQL_P: int =  getIndex("eql?");
    public static var TO_HASH: int =  getIndex("to_hash");
    public static var METHOD_MISSING: int =  getIndex("method_missing");
    public static var DEFAULT: int =  getIndex("default");
    
    public static function getIndex( methodName:String ):Number {
        var index: Object =  NUMBERS[methodName];
        
        if (index == null ) {
            index = new Number(NAMES.size());
            NUMBERS.put(methodName, index);
            NAMES.add(methodName);
        }
        
        return Number(index);
    }
    
    public static function getCallSite( name:String):CallSite {    
    	return new InlineCachingCallSite(name, CallType.NORMAL); 
    }
    
    public static function getFunctionalCallSite(name:String):CallSite {
        return new InlineCachingCallSite(name, CallType.FUNCTIONAL);
    }
    
    public static function getVariableCallSite(name:String):CallSite {
        return new InlineCachingCallSite(name, CallType.VARIABLE);
    }
}
}